package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.SizeConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.elasticsearch.constant.EsNormalConstant;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.model.PaasFormDataEsModel;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.feign.WorkOrderV2ExplainFeignClient;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.LinkInfoPojo;
import com.xbongbong.paas.field.LinkedAttrPoJo;
import com.xbongbong.paas.help.PaasFormHelp;
import com.xbongbong.paas.help.UserHelp;
import com.xbongbong.paas.help.analysis.data.FormDataLinkSearchAnalysisDataHelp;
import com.xbongbong.paas.help.service.impl.LinkDataBoolQueryBuilderServiceImpl;
import com.xbongbong.paas.help.service.impl.LinkSearchBoolQueryBuilderServiceImpl;
import com.xbongbong.paas.model.LinkDataModel;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.ButtonPojo;
import com.xbongbong.paas.pojo.dto.LinkDataListDTO;
import com.xbongbong.paas.pojo.dto.LinkSearchListDTO;
import com.xbongbong.paas.pojo.dto.ParseSingleRowDataDTO;
import com.xbongbong.paas.pojo.dto.UserAndDepartmentGetDTO;
import com.xbongbong.paas.pojo.linkdata.LinkDataExplainVO;
import com.xbongbong.paas.pojo.linkdata.dto.LinkDataExplainDTO;
import com.xbongbong.paas.pojo.vo.LinkDataListVO;
import com.xbongbong.paas.pojo.vo.LinkResultDataVO;
import com.xbongbong.paas.pojo.vo.LinkSearchListVO;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.pojo.vo.UserAndDepartmentGetVO;
import com.xbongbong.paas.service.LinkDataService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.ItemUtil;
import com.xbongbong.parent.parse.data.BaseFormDataLinkDataHelp;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.PaasStageEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.dto.LinkDataInfoDTO;
import com.xbongbong.pro.formdata.pojo.dto.LinkQueryDTO;
import com.xbongbong.pro.formdata.pojo.vo.FormDataVO;
import com.xbongbong.pro.formdata.pojo.vo.LinkQueryVO;
import com.xbongbong.pro.permission.pojo.dto.VerifyAddPermissionDTO;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkOrderExplainEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.help.FormDataAnalysisHelp;
import com.xbongbong.saas.help.LabelHelp;
import com.xbongbong.saas.help.SaasFormHelp;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.saas.util.SpecificationUtil;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author 吴峰
 * @date 2022/04/13 15:06
 */
@Service("linkDataServiceImpl")
public class LinkDataServiceImpl implements LinkDataService {

    private static final Logger LOG = LoggerFactory.getLogger(LinkDataServiceImpl.class);

    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasFormHelp paasFormHelp;
    @Resource
    private LinkSearchBoolQueryBuilderServiceImpl linkSearchBoolQueryBuilderService;
    @Resource
    private PaasFormDataEsModel paasFormDataEsModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private SaasFormHelp saasFormHelp;
    @Resource
    private LinkDataBoolQueryBuilderServiceImpl linkDataBoolQueryBuilderService;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private LinkDataModel linkDataModel;
    @Resource
    private LabelHelp labelHelp;
    @Resource
    private BaseFormDataLinkDataHelp baseFormDataLinkDataHelp;
    @Resource
    private UserHelp userHelp;
    @Resource
    private FormDataLinkSearchAnalysisDataHelp formDataLinkSearchAnalysisDataHelp;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private WorkOrderV2ExplainFeignClient workOrderV2ComboFeignClient;
    @Resource
    private FormDataAnalysisHelp formDataAnalysisHelp;


    @Override
    public LinkSearchListVO filterLinkSearch(LinkSearchListDTO linkSearchListDTO) throws XbbException {
        LinkSearchListVO linkDataVO;
        try {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            String corpid = linkSearchListDTO.getCorpid();
            LinkInfoPojo linkInfoPojo = linkSearchListDTO.getLinkInfo();
            PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(linkInfoPojo.getLinkFormId(), linkSearchListDTO.getCorpid());
            if ( Objects.isNull(paasFormExplainEntity) ) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            Map<String, FieldAttrEntity> explainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for ( FieldAttrEntity item : explainList ) {
                explainMap.put(item.getAttr(), item);
            }
            LinkQueryDTO linkQueryDTO = new LinkQueryDTO();
            BeanUtil.copyProperties(linkSearchListDTO, linkQueryDTO);
            linkQueryDTO.setExplainMap(explainMap);
            LinkQueryVO linkQueryVO = paasFormHelp.getLinkBoolQueryBuilder(linkQueryDTO, boolQueryBuilder);
            List<String> fieldList = linkQueryVO.getFieldList();
            explainList = linkQueryVO.getExplainList();
            explainMap = linkQueryVO.getExplainMap();
            // 获取boolQueryBuilder
            linkSearchBoolQueryBuilderService.getBoolQueryBuilder(boolQueryBuilder, linkSearchListDTO);
            //排序
            SortOrder order = SortOrder.DESC;
            String sortField = "updateTime";
            sourceBuilder.sort(new FieldSortBuilder(sortField).order(order));
            //限定返回值
            EsUtil.setFieldList(sourceBuilder, fieldList);
            IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(corpid, linkSearchListDTO.getLinkInfo().getLinkBusinessType(), linkSearchListDTO.getLinkInfo().getLinkSaasMark());


            //设置分页信息
            Integer page = linkSearchListDTO.getPage();
            Integer pageSize = linkSearchListDTO.getPageSize();
            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, page, pageSize);
            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,indexTypeEnum.getType()));
            sourceBuilder.query(boolQueryBuilder);
            SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
            searchRequest.source(sourceBuilder);
            linkDataVO = paasFormDataEsModel.filterLinkSearch(pageRequest, searchRequest, page, pageSize);
            // 解析成员和部门数据
            // ---- 获取用户和部门容器start
            UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
            BeanUtil.copyProperties(linkSearchListDTO, userAndDepartmentGetDTO);
            userAndDepartmentGetDTO.setExplainList(explainList);
            List<FormDataVO> paasFormDataESList = linkDataVO.getPaasFormDataESList();
            ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
            BeanUtil.copyProperties(linkSearchListDTO, parseSingleRowDataDTO);
            parseSingleRowDataDTO.setExplainMap(explainMap);
            parseSingleRowDataDTO.setExplainList(explainList);
            linkDataVO.setPaasFormDataESList(getFormDataList(paasFormDataESList, parseSingleRowDataDTO, userAndDepartmentGetDTO, linkInfoPojo));
        } catch (XbbException e) {
            LOG.error("paasFormData#filterLinkSearch关联查询出错", e);
            throw e;
        } catch (Exception e) {
            LOG.error("paasFormData#filterLinkSearch关联查询出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return linkDataVO;
    }

    @Override
    public LinkDataListVO filterLinkData(LinkDataListDTO linkDataListDTO) throws XbbException {
        LinkDataListVO linkDataVO = new LinkDataListVO();
        try {
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            LinkInfoPojo linkInfoPojo = linkDataListDTO.getLinkInfo();
            String corpid = linkDataListDTO.getCorpid();
            Integer businessType = linkInfoPojo.getLinkBusinessType();
            PaasFormExplainEntity paasFormExplainEntity = new PaasFormExplainEntity();
            if ( Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), businessType) ) {
                // 工单逻辑
                WorkOrderExplainEntityExt workOrderExplainEntityExt = workOrderExplainModel.getByFormId(linkInfoPojo.getLinkFormId(), corpid);
                if ( Objects.isNull(workOrderExplainEntityExt) ) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
                }
                BeanUtil.copyProperties(workOrderExplainEntityExt, paasFormExplainEntity);
            } else {
                paasFormExplainEntity = paasFormExplainModel.getByFormId(linkInfoPojo.getLinkFormId(), linkDataListDTO.getCorpid());
            }
            if ( Objects.isNull(paasFormExplainEntity) ) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            if (Objects.equals(paasFormExplainEntity.getDistributorMark(), DistributorMarkEnum.DISTRIBUTOR.getCode())) {
                Boolean enable = paasAppModel.validateAppEnable(null, XbbRefTypeEnum.DISTRIBUTOR.getAlias(), SaasMarkEnum.SAAS.getCode(), corpid);
                if (!enable) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.DISTRIBUTOR_DISABLE);
                }
            }
            List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            Map<String, FieldAttrEntity> explainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for ( FieldAttrEntity item : explainList ) {
                if (Objects.equals(item.getSaasAttr(), ProductEnum.UNIT.getSaasAttr()) && Objects.equals(businessType, XbbRefTypeEnum.PRODUCT.getCode())) {
                    List<ItemPoJo> productItems = saasFormHelp.getProductItems(corpid);
                    item.setItems(productItems);
                }
                explainMap.put(item.getAttr(), item);
            }
            if ( Objects.nonNull(linkInfoPojo.getLinkKeyAttr()) ) {
                LinkedAttrPoJo fieldAttrEntity = new LinkedAttrPoJo();
                BeanUtil.copyProperties(linkInfoPojo.getLinkKeyAttr(), fieldAttrEntity);
                List<LinkedAttrPoJo> linkedAttrPoJoList = new ArrayList<>();
                // 将关联数据的主键字段，放在第一个位置
                linkedAttrPoJoList.add(fieldAttrEntity);

                Integer targetFieldType = linkInfoPojo.getLinkKeyAttr().getFieldType();
                if (Objects.nonNull(explainMap.get(linkInfoPojo.getLinkKey()))) {
                    //标识如果关联数据中有阶段推进器字段，检索数据返回字段需要加上流程阶段id
                    targetFieldType = explainMap.get(linkInfoPojo.getLinkKey()).getFieldType();
                }
                boolean hasStageField = Objects.equals(targetFieldType, FieldTypeEnum.STAGE_THRUSTER.getType());
                if (CollectionsUtil.isNotEmpty(linkDataListDTO.getFieldList())) {
                    List<LinkedAttrPoJo> fieldList = linkDataListDTO.getFieldList();
                    for (LinkedAttrPoJo item : fieldList) {
                        FieldAttrEntity targetFieldAttr =  explainMap.get(item.getAttr());
                        if (Objects.nonNull(targetFieldAttr)) {
                            targetFieldType = targetFieldAttr.getFieldType();
                        }
                        if (Objects.equals(targetFieldType, FieldTypeEnum.STAGE_THRUSTER.getType())) {
                            hasStageField = true;
                            break;
                        }
                    }
                    linkedAttrPoJoList.addAll(linkDataListDTO.getFieldList());
                }
                if (hasStageField) {
                    LinkedAttrPoJo stageProcessId = new LinkedAttrPoJo();
                    BeanUtil.copyProperties(explainMap.get(PaasStageEnum.STAGE_PROCESS_ID.getAttr()), stageProcessId);
                    linkedAttrPoJoList.add(stageProcessId);
                }
                linkDataListDTO.setFieldList(linkedAttrPoJoList);
            }
            LinkQueryDTO linkQueryDTO = new LinkQueryDTO();
            BeanUtil.copyProperties(linkDataListDTO, linkQueryDTO);
            linkQueryDTO.setExplainMap(explainMap);
            // 模糊查询数据拼装
            LinkQueryVO linkQueryVO = paasFormHelp.getLinkBoolQueryBuilder(linkQueryDTO, boolQueryBuilder);
            List<String> fieldList = linkQueryVO.getFieldList();
            explainList = linkQueryVO.getExplainList();
            explainMap = linkQueryVO.getExplainMap();
            // 拼装数据
            Boolean result = linkDataBoolQueryBuilderService.getBoolQueryBuilder(boolQueryBuilder, linkDataListDTO);
            if ( !result ) {
                linkDataVO.setPaasFormDataESList(new ArrayList<>());
                PageHelper pageHelper = new PageHelper(linkDataListDTO.getPage());
                linkDataVO.setPageHelper(pageHelper);
                return linkDataVO;
            }

            // 当条件满足时，确保字段都存在，避免返回空列表
            List<String> list = EsUtil.mergeDataIdList(fieldList);
            BoolQueryBuilder isNotEmpty = boolQuery();
            for ( String s : list ) {
                String attr = s;
                if ( s.contains(StringConstant.POINT) ) {
                    attr = attr.split("\\.")[1];
                }
                FieldAttrEntity fieldAttrEntity = explainMap.get(attr);
                if ( Objects.isNull(fieldAttrEntity) ) {
                    continue;
                }
                BoolQueryBuilder boolQuery = boolQuery();

                FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldAttrEntity.getFieldType());
                switch (fieldTypeEnum) {
                    case TEXT:
                    case TEXTAREA:
                    case COMBO:
                    case RADIO_GROUP:
                    case SERIALNO:
                    case STAGE_THRUSTER:
                        // 过滤掉为空的情况
                        boolQuery.filter(existsQuery(s));
                        boolQuery.mustNot(termQuery(s + ".keyword", ""));
                        break;
                    case ADDRESS:
                        // 过滤掉为空的情况
                        boolQuery.filter(existsQuery(s));
                        String provinceKey = StringConstant.POINT + BusinessConstant.PROVINCE;
                        boolQuery.mustNot(termQuery(s + provinceKey + ".keyword", ""));
                        break;
                    case SUB_FORM:
                    case CONTACT_NUMBER:
                    case SWITCH_TEXT:
                    case SINGLE_SUB_FORM:
                        break;
                    default:
                        boolQuery.filter(existsQuery(s));
                        break;
                }
                if ( !list.isEmpty() ) {
                    isNotEmpty.minimumShouldMatch(EsNormalConstant.MINI_MUM_SHOULD_MATCH);
                    isNotEmpty.should(boolQuery);
                }
            }
            boolQueryBuilder.filter(isNotEmpty);

            IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(corpid, businessType, linkInfoPojo.getLinkSaasMark());

            // 排序
            sourceBuilder.sort(new FieldSortBuilder(FieldTypeEnum.UPDATETIME.getAlias()).order(SortOrder.DESC));
            sourceBuilder.sort(new FieldSortBuilder(BusinessConstant.ID).order(SortOrder.ASC));
            //限定返回值
            Boolean isProduct = Objects.equals(XbbRefTypeEnum.PRODUCT.getCode(), businessType);
            if ( isProduct ) {
                fieldList.add(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
                fieldList.add(ProductEnum.SPECIFICATION.getAttr());
            }
            EsUtil.setFieldList(sourceBuilder, fieldList, businessType);
            if ( isProduct ) {
                // 产品相关查询逻辑，这里检索的是子产品
                List<String> parentFieldList = new ArrayList<>();
                parentFieldList.add(StringConstant.DATA_ID);
                List<ProductEntityExt> productProduct = paasEsModel.getDataList(boolQueryBuilder, IndexTypeEnum.IDX_SAAS_PRODUCT, parentFieldList, 0, SizeConstant.PAGE_SIZE,  ProductEntityExt.class, FieldTypeEnum.UPDATETIME.getAlias(), SortOrder.DESC);
                if ( CollectionsUtil.isNotEmpty(productProduct) ) {
                    List<Long> dataIdList = new ArrayList<>();
                    productProduct.forEach(item -> {
                        dataIdList.add(item.getDataId());
                    });
                    BoolQueryBuilder childBuilder = boolQuery();
                    childBuilder.filter(termQuery("corpid.keyword", corpid));
                    childBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                    childBuilder.filter(termsQuery(StringConstant.JSON_DATA + StringConstant.POINT + ProductEnum.PARENT_ID.getAttr(), dataIdList));
                    childBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,indexTypeEnum.getType()));
                    SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
                    sourceBuilder.query(childBuilder);

                    //设置分页信息
                    Integer page = linkDataListDTO.getPage();
                    Integer pageSize = linkDataListDTO.getPageSize();
                    PageRequest pageRequest = EsUtil.setPage(sourceBuilder, page, pageSize);
                    searchRequest.source(sourceBuilder);
                    linkDataVO = linkDataModel.filterLinkData(corpid, linkInfoPojo, pageRequest, searchRequest, linkQueryVO, page, pageSize);
                    List<FormDataVO> paasFormDataESList = linkDataVO.getPaasFormDataESList();
                    if (CollectionsUtil.isNotEmpty(paasFormDataESList) && fieldList.contains(ProductEnum.SPECIFICATION.getAttr())) {
                        SpecificationUtil.formatChildSpecification4LinkData(paasFormDataESList, corpid);
                    }
                } else {
                    linkDataVO.setPaasFormDataESList(new ArrayList<>());
                    PageHelper pageHelper = new PageHelper(linkDataListDTO.getPage(), linkDataListDTO.getPageSize());
                    pageHelper.setRowsCount(0);
                    linkDataVO.setPageHelper(pageHelper);
                }
            } else {
                SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
                boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,indexTypeEnum.getType()));
                sourceBuilder.query(boolQueryBuilder);
                //设置分页信息
                Integer page = linkDataListDTO.getPage();
                Integer pageSize = linkDataListDTO.getPageSize();
                PageRequest pageRequest = EsUtil.setPage(sourceBuilder, page, pageSize);
                searchRequest.source(sourceBuilder);
                linkDataVO = linkDataModel.filterLinkData(corpid, linkInfoPojo, pageRequest, searchRequest, linkQueryVO, page, pageSize);
            }
            // 解析成员和部门数据
            // ---- 获取用户和部门容器start
            UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
            BeanUtil.copyProperties(linkDataListDTO, userAndDepartmentGetDTO);
            Set<String> set = new HashSet<>();
            Iterator<FieldAttrEntity> iterator = explainList.iterator();
            List<FieldAttrEntity> fieldAttrList = new ArrayList<>();
            while (iterator.hasNext()) {
                FieldAttrEntity fieldAttrEntity = iterator.next();
                // 去重并保持有序
                if ( set.add(fieldAttrEntity.getAttr()) ) {
                    // 移动端不显示子表单/附件、图片、定位数据
                    Boolean notDisplay = ExplainUtil.isSubForm(fieldAttrEntity.getFieldType())
                            || Objects.equals(FieldTypeEnum.IMAGE.getType(), fieldAttrEntity.getFieldType())
                            || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldAttrEntity.getFieldType())
                            || Objects.equals(FieldTypeEnum.UPLOAD.getType(), fieldAttrEntity.getFieldType());
                    if ( notDisplay && Objects.equals(PlatFormEnum.DINGTALK.getValue(), linkDataListDTO.getPlatform()) ) {
                        continue;
                    }
                    fieldAttrList.add(fieldAttrEntity);
                }
            }
            List<FormDataVO> paasFormDataESList = linkDataVO.getPaasFormDataESList();
            if (Objects.equals(linkInfoPojo.getLinkBusinessType(), XbbRefTypeEnum.WORK_ORDER_V2.getCode())) {
                LinkDataExplainDTO linkDataExplainDTO = new LinkDataExplainDTO(fieldAttrList, paasFormDataESList, corpid, linkInfoPojo.getLinkBusinessType());
                XbbResponse<LinkDataExplainVO> xbbResponse = workOrderV2ComboFeignClient.getExplain(linkDataExplainDTO, LocaleContextHolder.getLocale().toString());
                if (xbbResponse.isSuccess()) {
                    fieldAttrList = xbbResponse.getResult().getExplainList();
                    Map<String, FieldAttrEntity> workOrderExplainMap = ExplainUtil.getExplainMapByList(fieldAttrList);
                    explainMap.putAll(workOrderExplainMap);
                }
            }
            userAndDepartmentGetDTO.setExplainList(fieldAttrList);
            ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
            BeanUtil.copyProperties(linkDataListDTO, parseSingleRowDataDTO);
            parseSingleRowDataDTO.setBusinessType(businessType);
            parseSingleRowDataDTO.setSaasMark(linkInfoPojo.getLinkSaasMark());
            parseSingleRowDataDTO.setExplainMap(explainMap);
            parseSingleRowDataDTO.setExplainList(fieldAttrList);
            List<FormDataVO> dataList = getFormDataList(paasFormDataESList, parseSingleRowDataDTO, userAndDepartmentGetDTO, linkInfoPojo);
            linkDataVO.setPaasFormDataESList(dataList);
            // 新建权限
            VerifyAddPermissionDTO verifyAddPermissionDTO = new VerifyAddPermissionDTO();
            BeanUtil.copyProperties(linkDataListDTO, verifyAddPermissionDTO);
            verifyAddPermissionDTO.setSaasMark(linkInfoPojo.getLinkSaasMark());
            verifyAddPermissionDTO.setBusinessType(linkInfoPojo.getLinkBusinessType());
            verifyAddPermissionDTO.setMenuId(linkInfoPojo.getLinkMenuId());
            List<ButtonPojo> buttonList = paasFormHelp.getAddButton(verifyAddPermissionDTO, linkInfoPojo.getLinkAppId(), linkInfoPojo.getLinkFormId());
            linkDataVO.setTopPermissions(buttonList);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("paasFormData.filterLinkData关联数据出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return linkDataVO;
    }


    /**
     * 关联查询和关联数据解析用户和部门
     *          再加上一个解析标签字段
     *
     * @param paasFormDataESList
     * @param parseSingleRowDataDTO
     * @param userAndDepartmentGetDTO
     * @return
     * @throws XbbException
     */
    public List<FormDataVO> getFormDataList(List<FormDataVO> paasFormDataESList,
                                            ParseSingleRowDataDTO parseSingleRowDataDTO,
                                            UserAndDepartmentGetDTO userAndDepartmentGetDTO, LinkInfoPojo linkInfoPojo) throws XbbException {
        List<FormDataVO> formDataList = new ArrayList<>();
        try {
            Set<Object> linkDataSet = new HashSet<>();
            UserAndDepartmentGetVO userAndDepartmentGetVO = userHelp.getUserDepartmentMap(userAndDepartmentGetDTO);
            Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
            Map<String, DepartmentEntity> departmentMap = userAndDepartmentGetVO.getDepartmentMap();
            parseSingleRowDataDTO.setUserMap(userMap);
            parseSingleRowDataDTO.setDepartmentMap(departmentMap);
            //设置解析的关联数据的formId
            parseSingleRowDataDTO.setFormId(linkInfoPojo.getLinkFormId());
            for (FormDataVO item : paasFormDataESList) {
                JSONObject data = item.getData() == null ? new JSONObject() : item.getData();
                data.put(FieldTypeEnum.SERIALNO.getAlias(), item.getSerialNo());
                parseSingleRowDataDTO.setDataJsonObject(data);
                // 解析数据
                ParseSingleRowDataVO parseSingleRowDataVO = formDataLinkSearchAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                if (Objects.isNull(parseSingleRowDataVO)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                LinkResultDataVO linkResultDataVO = parseSingleRowDataVO.getLinkResultDataVO();
                if (!linkResultDataVO.getLinkDataSet().isEmpty()) {
                    linkResultDataVO.getLinkDataSet().forEach((itemId -> {
                        linkDataSet.add(itemId);
                    }));
                }
                JSONObject result = parseSingleRowDataVO.getResult();
                // fix：45437 【阶段推进器】app端-选择关联数据处，不应有数字展示
                // 在关联数据中，不展示阶段流程id，阶段id，阶段比例,因为这三个字段在关联数据中本就无法选中
                if (Objects.nonNull(result)){
                    result.remove(PaasStageEnum.STAGE_PROCESS_ID.getAttr());
                    result.remove(PaasStageEnum.STAGE_ID.getAttr());
                    result.remove(PaasStageEnum.STAGE_RATIO.getAttr());
                }
                item.setData(result);
                if (Objects.equals(PlatFormEnum.DINGTALK.getValue(), parseSingleRowDataDTO.getPlatform())) {
                    LinkDataInfoDTO linkDataInfoDTO = new LinkDataInfoDTO();
                    BeanUtil.copyProperties(parseSingleRowDataDTO, linkDataInfoDTO);
                    linkDataInfoDTO.setSerialNo(item.getSerialNo());
                    linkDataInfoDTO.setData(result);
                    linkDataInfoDTO.setExplainList(parseSingleRowDataDTO.getExplainList());
                    linkDataInfoDTO.setLinkInfoPojo(linkInfoPojo);
                    linkDataInfoDTO.setExplainMap(parseSingleRowDataDTO.getExplainMap());
                    item.setLinkData(getLinkDataInfoStr(linkDataInfoDTO));
                }
                formDataList.add(item);
            }
            // 千分位解析
            analysisAmountOfThousandBits(paasFormDataESList, parseSingleRowDataDTO.getExplainList());
            labelHelp.changeDataLabel(formDataList, parseSingleRowDataDTO, linkInfoPojo);
        } catch (Exception e) {
            LOG.error("paasFormData.getFormDataList出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return formDataList;
    }


    /**
     * 单独拎出来 解析千份位 测试完后再放出
     * @param list 数据
     * @throws XbbException
     */
    public void analysisAmountOfThousandBits(List<FormDataVO> list, List<FieldAttrEntity> fieldAttrEntityList){
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        Map<String,Object> explainMap = FormDataAnalysisHelp.needAnalysisFieldAttr(fieldAttrEntityList);
        if (MapUtils.isEmpty(explainMap)) {
            return;
        }
        for(FormDataVO paasFormDataEntityExt : list){
            JSONObject resultJson = paasFormDataEntityExt.getData();
            Iterator iterator = resultJson.keySet().iterator();
            while (iterator.hasNext()){
                String attr = iterator.next().toString();
                formDataAnalysisHelp.analysisAmountOfThousandBitsNomal(resultJson,attr,explainMap, false);
            }
            paasFormDataEntityExt.setData(resultJson);
        }
    }
    /**
     * 将关联数据的拼接转成字符串
     * @param linkDataInfoDTO
     * @return
     * @throws XbbException
     */
    public String getLinkDataInfoStr(LinkDataInfoDTO linkDataInfoDTO) throws XbbException {
        String linkData = "";
        try {
            List<FieldAttrEntity> explainList = linkDataInfoDTO.getExplainList();
            JSONObject data = baseFormDataLinkDataHelp.getLinkDataInfo(linkDataInfoDTO);
            List<String> list = new ArrayList<>();
            for (FieldAttrEntity fieldAttrEntity : explainList) {
                Integer fieldType = fieldAttrEntity.getFieldType();
                String key = fieldAttrEntity.getAttr();
                if (Objects.isNull(data.get(key))) {
                    continue;
                }
                if(FieldTypeEnum.ADDRESS.getType().equals(fieldType)) {
                    // 多选转化成逗号隔开的字符串
                    if (data.get(key) instanceof JSONObject) {
                        JSONObject addressData = data.getJSONObject(key);
                        String province = FastJsonHelper.getStringOrDefaultFromFormData(addressData, BusinessConstant.PROVINCE, "");
                        String district = FastJsonHelper.getStringOrDefaultFromFormData(addressData, BusinessConstant.DISTRICT, "");
                        String city = FastJsonHelper.getStringOrDefaultFromFormData(addressData, BusinessConstant.PROVINCE, "");
                        String address = "";
                        if (Objects.equals(1, fieldAttrEntity.getShowDetailAddress())) {
                            address = FastJsonHelper.getStringOrDefaultFromFormData(addressData, BusinessConstant.ADDRESS, "");
                        }
                        if (StringUtil.isNotEmpty(province) && StringUtil.isNotEmpty(district) && StringUtil.isNotEmpty(city) && StringUtil.isNotEmpty(address)) {
                            String addressValue = province + city + district + address;
                            list.add(addressValue);
                        }
                    } else {
                        list.add(data.getString(key));
                    }

                } else if(FieldTypeEnum.DATETIME.getType().equals(fieldType)){
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(fieldAttrEntity.getDateType());
                    Date date = new Date(data.getLong(key)*1000L);
                    String dateValue = DateUtil.getString(date, simpleDateFormat);
                    list.add(dateValue);
                }else if(FieldTypeEnum.RADIO_GROUP.getType().equals(fieldType)
                        || FieldTypeEnum.COMBO.getType().equals(fieldType)
                        ||FieldTypeEnum.STAGE_THRUSTER.getType().equals(fieldType)){
                    Object itemValue = data.get(key);
                    list.add(Objects.isNull(itemValue) ? null : ItemUtil.parseItemPoJoFromFormData2String(data, key, ""));
                } else if(FieldTypeEnum.CHECKBOX_GROUP.getType().equals(fieldType)
                        || FieldTypeEnum.COMBO_CHECK.getType().equals(fieldType)) {
                    // 多选转化成逗号隔开的字符串
                    Object itemValue = data.get(key);
                    list.add(Objects.isNull(itemValue) ? null : ((List<ItemPoJo>) itemValue).stream().map(ItemPoJo::getText).collect(Collectors.joining("、")));
                } else if (FieldTypeEnum.USER_GROUP.getType().equals(fieldType)
                        || FieldTypeEnum.DEPT_GROUP.getType().equals(fieldType)) {
                    List<ReturnUserAndDepartmentPojo> result = data.getJSONArray(key).toJavaList(ReturnUserAndDepartmentPojo.class);
                    List<String> nameList = new ArrayList<>();
                    result.forEach(item->{
                        nameList.add(item.getName());
                    });
                    list.add(StringUtils.join(nameList, "、"));
                }  else if (FieldTypeEnum.USER.getType().equals(fieldType) || FieldTypeEnum.DEPT.getType().equals(fieldType)) {
                    ReturnUserAndDepartmentPojo returnUserAndDepartmentPojo = data.getJSONObject(key).toJavaObject(ReturnUserAndDepartmentPojo.class);
                    list.add(returnUserAndDepartmentPojo.getName());
                } else if (FieldTypeEnum.LABEL.getType().equals(fieldType)){
                    JSONArray jsonArray = data.getJSONArray(key);
                    LinkInfoPojo linkInfoPojo = linkDataInfoDTO.getLinkInfoPojo();
                    if (CollectionsUtil.isNotEmpty(jsonArray) && Objects.nonNull(linkInfoPojo)) {
                        labelHelp.getList(jsonArray, list, linkDataInfoDTO.getCorpid(), linkInfoPojo.getLinkFormId(), linkInfoPojo.getLinkAppId());
                    }
                }else {
                    list.add(data.getString(key));
                }
            }
            linkData = StringUtils.join(list, "；");
        } catch (Exception e) {
            LOG.error("formDataService.getLinkDataInfo执行出错：", e);
        }
        return linkData;
    }

}
